
#include "sleipner_config.h"
#include "pvu_shadow.h"

#include "graphics/graphics.h"
#include "graphics/image.h"
#include "graphics/surface.h"
#include "graphics/graphics_util.h"
#include "graphics/image_cache.h"

#include "dd/dd_man.h"
#include "util/log.h"				// log
#include "util/common_macros.h"		// macros
#include "util/mmgr.h"		    


#include <algorithm>
#include <cassert>

PVUShadow::PVUShadow() :
	m_pCache(0),
	m_OverlayA(0)
{

}
PVUShadow::~PVUShadow()
{
	UTIL_SAFE_DELETEA(m_OverlayA);
	UTIL_SAFE_DELETE(m_pCache);
}

bool 	PVUShadow::Init(int	Width, int Height, int	Depth)
{
	if (m_pCache) return false;	// already exists
#ifdef _PLATFORM_WII
	m_pCache = GetGraphics()->CreateCache(512, 256, 8);
#else
	m_pCache = GetGraphics()->CreateCache(Width, Height, 32);
#endif
	return true;
}
bool	PVUShadow::StartCache()
{
	if (!m_pCache->BeginCache()) return false;
#ifdef _PLATFORM_WIN32
	GetGraphics()->SetRenderState( Graphics::RS_ALPHA_TEST, true );
	GetGraphics()->SetRenderState( Graphics::RS_ALPHA_REF, 0xFA);
#endif
#ifdef _PLATFORM_WII
	GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_RASC, GX_CC_ZERO, GX_CC_ZERO,GX_CC_ZERO);
	GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
#endif

	m_pCache->ClearCache(ColorRGBA(0,0,0, 0));
	return true;
}
bool	PVUShadow::EndCache()
{
	if (!m_pCache) return false;
	GetGraphics()->SetRenderState( Graphics::RS_ALPHA_REF, 0x05);
	m_pCache->EndCache();
#ifdef _PLATFORM_WII
	GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_TEXC, GX_CC_RASC, GX_CC_ZERO,GX_CC_ZERO);
	GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
#endif
	return true;
}

bool	PVUShadow::ShowCache()
{
	if (!m_pCache) return false;
	Graphics::Vertex2D	VertA[6];
#ifdef _PLATFORM_WII
	//COLOR	c = m_ShadowColor;
	COLOR	c = ColorRGBA(55, 55, 55, 180);
	GraphicsUtil::FillQuad(math::Vec2(0,0), math::Vec2(1,1), math::Vec2(0,0), 
		math::Vec2((float)GetGraphics()->GetScreenWidth()*0.5f / (float)m_pCache->GetWidth() , (float)GetGraphics()->GetScreenHeight() *0.5f/ (float)m_pCache->GetHeight()), 
		c, VertA); 
#elif _PlATFORM_SDL  
	COLOR	c = ColorRGBA(255, 255, 255, 50);
	GraphicsUtil::FillQuad(math::Vec2(0,0), math::Vec2(1,1), math::Vec2(0,0), math::Vec2((float)GetGraphics()->GetScreenWidth() / (float)m_pCache->GetWidth() , (float)GetGraphics()->GetScreenHeight() / (float)m_pCache->GetHeight()), c, VertA); 
#else
	COLOR	c = ColorRGBA(255, 255, 255, 50);
	GraphicsUtil::FillQuad(math::Vec2(0,0), math::Vec2(1,1), math::Vec2(0,(float)GetGraphics()->GetScreenWidth()/ (float)m_pCache->GetHeight()), math::Vec2((float)GetGraphics()->GetScreenWidth() / (float)m_pCache->GetWidth() , 0), c, VertA); 
#endif
	m_pCache->SetTextureStage(0);
	GetGraphics()->DrawVertex2D(VertA, 6);

	return true;
}

void		PVUShadow::CreateOverlay(int w, int h, const std::string& Base)
{
	if (m_OverlayA) return;
	m_OverlayA = new ui::UISprite[w*h];
	m_OverlayX = w;
	m_OverlayY = h;

	for (int x=0; x<w; x++)
	for (int y=0; y<h; y++)
	{
		char	Buffer[256];
		sprintf(Buffer, "%s%02i_%02i_shadow.png", Base.c_str(), x+1, y+1);
		m_OverlayA[x + (y*w)].Create(Buffer);
	}

}
void		PVUShadow::RenderOverlay(const math::Vec2& Offset, float Scale)
{
	if (!m_OverlayA) return;
	const math::Vec2	BaseSize(1024*GraphicsUtil::InvW, 1024*GraphicsUtil::InvH); 
	for (int x=0; x<m_OverlayX; x++)
	for (int y=0; y<m_OverlayY; y++)
	{
		ui::UISprite* pSprite = &m_OverlayA[x + (y*m_OverlayX)];
		pSprite->m_Size = BaseSize*Scale;
		pSprite->m_Pos.x = ((x * BaseSize.x) - Offset.x)*Scale;
		pSprite->m_Pos.y = ((y * BaseSize.y) - Offset.y)*Scale;

		// if it's visible
		if (pSprite->m_Pos.x > 1 || 
			pSprite->m_Pos.y > 1 ||	
			pSprite->m_Pos.x + pSprite->m_Size.x < 0 || 
			pSprite->m_Pos.y +pSprite->m_Size.y < 0) continue;

		pSprite->m_Color = ColorRGBA(255, 255, 255, 150);
		pSprite->Render();
	}
}
